#ifndef TIMEWHEEL
#define TIMEWHEEL

#include "Channel.h"
#include <sys/timerfd.h>
#include <memory>
#include <functional>
/**
 * timerfd:给进程一个超时的信号
 * timewheel：执行超时的任务
 */
class EventLoop;

using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;
constexpr int capa = 60;

class TimerTask
{
public:
    TimerTask(uint64_t id, uint32_t delay, const TaskFunc &cb);
    void SetCancle();
    bool getCancle();
    void SetRelease(ReleaseFunc rel);
    ~TimerTask();

    uint32_t getTimeOut();
    const TaskFunc &getTaskFunc() const;

private:
    uint64_t _id;         // 定时器id
    uint32_t _timeout;    // 超时时间
    bool _iscancel;       // 是否被取消，false否，true是
    TaskFunc _task_cb;    // 定时器结束后要回调执行的定时任务，
    ReleaseFunc _relfunc; // 释放任务的回调函数
};

class TimeWheel
{
    using PtrTask = std::shared_ptr<TimerTask>;
    using WeakTask = std::weak_ptr<TimerTask>;

private:
    void TimerRemove(uint64_t id);
    static int CreateTimerFd();
    uint64_t ReadTimerFd();
    void TimerAddInLoop(uint64_t id, uint32_t delay, const TaskFunc &tf);
    void TimerRefershInLoop(uint64_t id);
    void TimerCancelInLopp(uint64_t id);
    void OnTime();

public:
    TimeWheel(EventLoop *loop);

    void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc &tf);

    void TimerRefersh(uint64_t id);

    void TimerCancel(uint64_t id);

    void RunTimerTask();
    /*这个接口存在线程安全问题--这个接口实际上不能被外界使用者调用，只能在模块内，在对应的EventLoop线程内执行 */
    bool HasTimer(uint64_t id);
    ~TimeWheel();

private:
    int _tick;            // 要执行的任务的指针，指向谁，谁就要执行
    int _capacity = capa; // 一个时间轮的最大单位，这里以秒为单位，最大为60
    // 用一个二维数组管理定时器
    std::vector<std::vector<PtrTask>> _wheel;
    // 使用弱指针管理，防止shared_ptr的循环引用问题
    std::unordered_map<uint64_t, WeakTask> _timer;

    EventLoop *_loop; // 描述符也是需要监听连接的，统一放在EventLoop中
    int _timerfd;     // 定时器描述符
    std::unique_ptr<Channel> _timer_channel;
};

#endif